package com.currency.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.currency.exception.AppException;
import com.currency.mapper.*;
import com.currency.pojo.*;
import com.currency.request.EnsureOfflineWithdrawalRequest;
import com.currency.request.OfflineWithdrawalRequest;
import com.currency.response.BaseResponse;
import com.currency.service.OfflineService;
import com.currency.util.WithdrawalUtil;
import com.currency.util.XmlToJson;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.math.BigDecimal;

@Slf4j
@Service("offlineService")
public class OfflineServiceImpl implements OfflineService {
    @Autowired
    private WytCurrencyOfflineWithdrawalMapper offlineWithdrawalMapper;

    @Autowired
    private PayAccountMapper payAccountMapper;

    @Autowired
    private WytCoinsTradeResumeMapper resumeMapper;

    @Autowired
    private WithdrawalDetailMapper withdrawalDetailMapper;

    @Autowired
    private CoinsFreezeMapper coinsFreezeMapper;

    @Value("${sys.certPath}")
    private String certPath;

    @Value("${sys.alipay.app_cert_path}")
    private String appCertPath;
    @Value("${sys.alipay.alipay_cert_path}")
    private String alipayCertPath;
    @Value("${sys.alipay.alipay_root_cert_path}")
    private String alipayRootCertPath;

    // 申请线下提现
    @PostMapping("offline-withdrawal")
    @ApiOperation("提现申请")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse offlineWithdrawal(@RequestBody OfflineWithdrawalRequest request) throws AppException {

        //查询用户信息
        WytCurrencyPayAccountPojo accountPojo = payAccountMapper.selectById(request.getUserId());
        if (accountPojo == null) {
            throw new AppException("cey9999", "未查询到用户");
        }
        WytCurrencyOfflineWithdrawalPojo pojo = new WytCurrencyOfflineWithdrawalPojo();
        pojo.setUserId(request.getUserId());
        pojo.setAmount(new BigDecimal(request.getAmount()));
        pojo.setWithdrawalType(request.getWithdrawalType());
        if (pojo.getWithdrawalType() == 0) {
            pojo.setWithdrawalType(WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_OFFLINE);
        }

        // 提现到微信时，需要提前确认客户是否已经绑定微信账号
        if (request.getWithdrawalType() == WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_WEIXIN && StringUtils.isBlank(accountPojo.getUserWxId())) {
            throw new AppException("cey1000", "客户需要先绑定微信后，才能申请微信提现");
        }

        // 提现到支付宝时，需要提前确认客户是否已经绑定支付宝账号
        if (request.getWithdrawalType() == WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_ALIPAY && StringUtils.isBlank(accountPojo.getUserApId())) {
            throw new AppException("cey1001", "客户需要先绑定支付宝后，才能申请微信提现");
        }


        BigDecimal bd = pojo.getAmount().multiply(new BigDecimal("100"));
        int cnt = bd.intValue();
        if (cnt > accountPojo.getUserCoins()) {
            throw new AppException("cey1010", "金币余额不足，无法提现");
        }
        // 冻结用户金币
        accountPojo.setUserCoins(accountPojo.getUserCoins() - cnt);
        accountPojo.setUserFreezeCoins(accountPojo.getUserFreezeCoins() + cnt);
        payAccountMapper.updateById(accountPojo);


        //插入申请
        offlineWithdrawalMapper.insert(pojo);

        // 放到冻结记录表
        WytCurrencyCoinsFreeze freeze = new WytCurrencyCoinsFreeze();
        freeze.setFreezeOrderId("Frz" + IdUtil.getSnowflake(10, 20).nextIdStr());
        freeze.setFreezeCoins(cnt);
        freeze.setFreezeOrderId(pojo.getId());
        freeze.setUserId(pojo.getUserId());
        freeze.setFreezeStatus(7);
        freeze.setFreezeStatus(WytCurrencyCoinsFreeze.FREEZE_STATUS_FREEZE);
        freeze.setFreezeReason("提现冻结金币");
        freeze.setUnfreezeReason(WytCurrencyCoinsFreeze.UNFREEZE_REASON_BACK);
        coinsFreezeMapper.insert(freeze);

        return new BaseResponse("cey0000", "提现申请通过");
    }

    // 通过线下提现申请
    @PostMapping("ensure-offline-withdrawal")
    @ApiOperation("提现申请通过")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse ensureOfflineWithdrawal(@RequestBody EnsureOfflineWithdrawalRequest request) throws Exception {
        // 查询订单信息
        WytCurrencyOfflineWithdrawalPojo pojo = offlineWithdrawalMapper.selectById(request.getId());
        if (pojo == null) {
            throw new AppException("cey1000", "未查询到预付款订单");
        }
        // 如果订单已经处理，防止重复审批
        if (pojo.getStatus() != 0) {
            throw new AppException("cey9998", "此订单已经进行过操作，请误重复提交");
        }
        //查询用户信息
        WytCurrencyPayAccountPojo accountPojo = payAccountMapper.selectById(pojo.getUserId());
        if (accountPojo == null) {
            throw new AppException("cey9999", "未查询到用户");
        }
        BigDecimal bd = pojo.getAmount().multiply(new BigDecimal("100"));
        int cnt = bd.intValue();
        // 减少用户金币
        accountPojo.setUserFreezeCoins(accountPojo.getUserFreezeCoins() - cnt);
        payAccountMapper.updateById(accountPojo);
        String wdlId = "wdl" + IdUtil.createSnowflake(1, 1).nextIdStr();
        WytCoinsTradeResumePojo resumePojo = new WytCoinsTradeResumePojo();
        WytCurrencyWithdrawalDetailPojo withdrawalPojo = new WytCurrencyWithdrawalDetailPojo();
        withdrawalPojo.setWdlId(wdlId);
        withdrawalPojo.setWdlAmount(pojo.getAmount());

        pojo.setRepayAdminUser(request.getRepayAdminUser());
        pojo.setRepayImage(request.getRepayImage());
        pojo.setRepayType(request.getRepayType());
        pojo.setStatus(1);
        //更新申请结果
        offlineWithdrawalMapper.updateById(pojo);
        if (pojo.getWithdrawalType() == WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_OFFLINE || StringUtils.equalsIgnoreCase(request.getOfflineRepayFlag(), "Y")) {
            // 如果是线下提现，则转账证据不能为空
            if (StringUtils.isBlank(request.getRepayImage())) {
                throw new AppException("cey7000", "线下提现图片不能为空");
            }
            withdrawalPojo.setWdlParams("线下提现");
            withdrawalPojo.setReturnParams("线下提现");
            withdrawalPojo.setWdlType(WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_OFFLINE);
            withdrawalPojo.setUserId(accountPojo.getUserId());
            withdrawalPojo.setWdlStatus(WytCurrencyWithdrawalDetailPojo.WDL_STATUS_SUCCESS);
            withdrawalDetailMapper.insert(withdrawalPojo);

        } else if (pojo.getWithdrawalType() == WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_OLI) {
            // 如果是提现到油卡 增加油卡信息
            accountPojo.setOilCoins(accountPojo.getOilCoins() + cnt);
            // 提现到油卡记录
            withdrawalPojo.setWdlParams("油卡提现");
            withdrawalPojo.setReturnParams("油卡提现");
            withdrawalPojo.setWdlType(WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_OLI);
            withdrawalPojo.setUserId(accountPojo.getUserId());
            withdrawalPojo.setWdlStatus(WytCurrencyWithdrawalDetailPojo.WDL_STATUS_SUCCESS);
            withdrawalDetailMapper.insert(withdrawalPojo);
        } else if (pojo.getWithdrawalType() == WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_WEIXIN) {
            // 如果是提现到微信
            // 第一步 补充添加数据
            withdrawalPojo.setWdlId(wdlId);
            withdrawalPojo.setWdlParams(wdlId + "&&" + accountPojo.getUserWxId() + "&&" + cnt + "&&" + certPath);
            withdrawalPojo.setWdlType(WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_WEIXIN);
            withdrawalPojo.setUserId(accountPojo.getUserId());
            withdrawalPojo.setWdlStatus(WytCurrencyWithdrawalDetailPojo.WDL_STATUS_SUCCESS);
            withdrawalDetailMapper.insert(withdrawalPojo);
            String ans;
            try {
                // 注意微信用分为单位
                ans = WithdrawalUtil.postForWxWithdrawal(wdlId, accountPojo.getUserWxId(), cnt, certPath);
            } catch (Exception e) {
                e.printStackTrace();
                throw new AppException("cey9999", "微信提现出现异常");
            }
            if (StringUtils.isNotBlank(ans)) {
                log.info("微信提现返回结果为：" + ans);
                JSONObject ansJson = XmlToJson.xml2Json(ans);
                if (StringUtils.equalsIgnoreCase(ansJson.getString("result_code"), "SUCCESS")) {
                    // 红包发送成功
                    withdrawalPojo.setReturnParams(ans);
                    // 更新数据库信息
                    withdrawalPojo.setWdlStatus(WytCurrencyWithdrawalDetailPojo.WDL_STATUS_SUCCESS);
                } else {
                    // 红包发送失败
                    throw new AppException("cey0010", "微信红包发送失败，具体原因为： " + ans + " 。如果无法理解请联系技术人员");
                }
            } else {
                // 红包发送失败
                throw new AppException("cey0010", "微信红包发送失败，具体原因为： " + ans + " 。如果无法理解请联系技术人员");
            }
            withdrawalDetailMapper.updateById(withdrawalPojo);
        } else if (pojo.getWithdrawalType() == WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_ALIPAY) {
            // 如果是提现到支付宝
            // 第一步 补充添加数据
            withdrawalPojo.setWdlId(wdlId);
            withdrawalPojo.setWdlParams(wdlId + "&&" + accountPojo.getUserApId() + "&&" + cnt + "&&" + certPath);
            withdrawalPojo.setWdlType(WytCurrencyOfflineWithdrawalPojo.WITHDRAWAL_TYPE_ALIPAY);
            withdrawalPojo.setUserId(accountPojo.getUserId());
            withdrawalPojo.setWdlStatus(WytCurrencyWithdrawalDetailPojo.WDL_STATUS_SUCCESS);
            withdrawalDetailMapper.insert(withdrawalPojo);
            AlipayFundTransUniTransferResponse ans;
            try {
                //注意支付宝以元为单位
                ans = WithdrawalUtil.postForAlipayWithdrawal(wdlId, accountPojo.getUserApId(), "", pojo.getAmount(), appCertPath, alipayCertPath, alipayRootCertPath);
            } catch (Exception e) {
                e.printStackTrace();
                throw new AppException("cey9999", "支付宝提现出现异常");
            }

            log.info(JSON.toJSONString(ans));
            if (ans.isSuccess()) {
                // 红包发送成功
                withdrawalPojo.setReturnParams(JSON.toJSONString(ans));
                // 更新数据库信息
                withdrawalPojo.setWdlStatus(WytCurrencyWithdrawalDetailPojo.WDL_STATUS_SUCCESS);
                log.info("调用成功");
            } else {
                log.warn("调用失败");
                throw new AppException("cey0010", "支付宝发送失败，具体原因为： " + JSON.toJSONString(ans) + " 。如果无法理解请联系技术人员");
            }

            withdrawalDetailMapper.updateById(withdrawalPojo);
        }

        //插入概要信息
        resumePojo.setId("resume" + IdUtil.createSnowflake(1, 2).nextIdStr());
        resumePojo.setUserId(accountPojo.getUserId());
        resumePojo.setAmount(pojo.getAmount());
        resumePojo.setType(WytCoinsTradeResumePojo.MUL_WITHDRAWAL);
        resumePojo.setOutId(wdlId);
        resumePojo.setMsg("提现金币扣减");
        resumeMapper.insert(resumePojo);

        // 解冻原先冻结的记录
        WytCurrencyCoinsFreeze freeze = coinsFreezeMapper.selectOne(new QueryWrapper<WytCurrencyCoinsFreeze>().eq("freeze_order_id", pojo.getId()));
        if (freeze != null) {
            freeze.setFreezeStatus(WytCurrencyCoinsFreeze.FREEZE_STATUS_THAW);
            coinsFreezeMapper.updateById(freeze);
        }

        return new BaseResponse("cey0000", "提现申请通过");
    }
}